package pprg.core;

/**
 * Representation of the game-world. The 2D world is represented by a 2D boolean
 * matrix, which is called board.
 * 
 * @author Daniel Heily, Michael Hinterleitner
 *
 */
public class World {

	private int x0;
	private int y0;
	private boolean[][] board;
	private int width;
	private int height;

	/**
	 * Create a game world
	 * 
	 * @param x0
	 *            the row index of the upper left corner
	 * @param y0
	 *            the column index of the upper left corner
	 * @param width
	 *            the width of the game world
	 * @param height
	 *            the height of the game world.
	 */
	public World(int x0, int y0, int width, int height) {
		this.setX0(x0);
		this.y0 = y0;
		this.width = width;
		this.height = height;
		board = new boolean[height][width];
	}

	/**
	 * Check if cell at x,y is alive
	 * 
	 * @param x
	 *            row index
	 * @param y
	 *            column index
	 * @return true if cell is alive.
	 */
	public boolean isAlive(int x, int y) {
		if (x < 0) {
			x = width - 1;
		}
		if (x >= width) {
			x = 0;
		}
		if (y < 0) {
			y = height - 1;
		}
		if (y >= height) {
			y = 0;
		}
		return board[y][x];
	}

	/**
	 * Set alive status for cell at x,y
	 * 
	 * @param alive
	 *            true or false
	 * @param x
	 *            row index
	 * @param y
	 *            column index
	 */
	public void setAlive(boolean alive, int x, int y) {
		board[y][x] = alive;
	}

	public void setBoard(boolean[][] board) {
		this.board = board;
	}

	public boolean[][] getBoard() {
		int length = board.length;
		boolean[][] target = new boolean[length][board[0].length];
		for (int i = 0; i < length; i++) {
			System.arraycopy(board[i], 0, target[i], 0, board[i].length);
		}
		return target;
	}

	public int getWidth() {
		return width;
	}

	public int getHeight() {
		return height;
	}

	/**
	 * copy a specifc part of the current world.
	 * 
	 * @param x
	 *            row index of upper left row
	 * @param y
	 *            column index of upper left column
	 * @param width
	 *            width of part to copy
	 * @param height
	 *            height of part to copy
	 * @return
	 */
	public World getSubWorld(int x, int y, int width, int height) {
		boolean[][] target = new boolean[height][width];
		int j = 0;
		int yWorld = y + 1;
		if (y < 0) {
			y = 0;
			j = 1;
			System.arraycopy(board[this.height - 1], 0, target[0], 0,
					board[this.height - 1].length);
		}
		if (y + height > board.length) {
			height = height - 1;
			j = 1;
			System.arraycopy(board[0], 0, target[height - 1], 0,
					board[0].length);
		}
		World subWorld = new World(x, yWorld, width, height);

		for (int i = y; i < y - j + height; i++) {
			System.arraycopy(board[i], 0, target[i + j - y], 0, board[i].length);
		}
		subWorld.setBoard(target);
		return subWorld;
	}

	public int getY0() {
		return y0;
	}

	public int getX0() {
		return x0;
	}

	public void setX0(int x0) {
		this.x0 = x0;
	}
}
